package com.xgk.boot.module.core.util;



import cn.hutool.extra.spring.SpringUtil;
import com.xgk.boot.framework.common.context.ElmOrderThreadContext;
import com.xgk.boot.module.core.mq.message.log.OrderApiLogMessage;
import com.xgk.boot.module.core.mq.producer.log.OrderApiLogProducer;
import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import okhttp3.internal.Util;


import javax.net.ssl.*;
import java.io.IOException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * 高性能HTTP工具类，支持1000+并发
 */
@Slf4j
public class HighHttpUtil {
    // 默认连接参数
    private static final int MAX_IDLE_CONNECTIONS = 200;
    private static final long KEEP_ALIVE_DURATION = 5L; // 分钟
    private static final int CONNECT_TIMEOUT = 10; // 秒
    private static final int READ_TIMEOUT = 30; // 秒
    private static final int WRITE_TIMEOUT = 30; // 秒

    // 媒体类型常量
    private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
    private static final MediaType FORM = MediaType.parse("application/x-www-form-urlencoded; charset=utf-8");

    // 客户端实例（使用volatile保证可见性）
    private static volatile OkHttpClient okHttpClient;

    // 请求标记缓存（用于取消请求）
    private static final Map<Object, Call> callCache = new ConcurrentHashMap<>();
    private static OrderApiLogProducer apiLogProducer;

    private static OrderApiLogProducer initApiLogProducer() {
        if (apiLogProducer == null) {
            synchronized (HighHttpUtil.class) {
                if (apiLogProducer == null) {
                    apiLogProducer = SpringUtil.getBean(OrderApiLogProducer.class);
                }
            }
        }
        return apiLogProducer;
    }
    /**
     * 初始化HTTP客户端（线程安全）
     */
    private static void initClient() {
        if (okHttpClient == null) {
            synchronized (HighHttpUtil.class) {
                if (okHttpClient == null) {
                    // 创建SSL上下文（信任所有证书，生产环境应配置正式证书）
                    SSLContext sslContext;
                    try {
                        sslContext = SSLContext.getInstance("SSL");
                        sslContext.init(null, new TrustManager[]{createTrustAllManager()}, new SecureRandom());
                    } catch (Exception e) {
                        throw new RuntimeException("SSL context initialization failed", e);
                    }

                    // 配置连接池
                    ConnectionPool connectionPool = new ConnectionPool(
                            MAX_IDLE_CONNECTIONS,
                            KEEP_ALIVE_DURATION,
                            TimeUnit.MINUTES);

                    // 构建客户端
                    okHttpClient = new OkHttpClient.Builder()
                            .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
                            .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
                            .writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS)
                            .connectionPool(connectionPool)
                            .sslSocketFactory(sslContext.getSocketFactory(), createTrustAllManager())
                            .hostnameVerifier((hostname, session) -> true) // 跳过主机名验证
                            .build();
                }
            }
        }
    }

    /**
     * 创建信任所有证书的TrustManager
     */
    private static X509TrustManager createTrustAllManager() {
        return new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) {}

            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) {}

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
        };
    }

    /**
     * 同步GET请求
     */
    public static Response get(String url) throws IOException {
        return get(url, null, null);
    }

    public static Response get(String url, Map<String, String> headers) throws IOException {
        return get(url, headers, null);
    }

    public static Response get(String url, Map<String, String> headers, Object tag) throws IOException {
        initClient();
        Request.Builder builder = new Request.Builder().url(url);
        addHeaders(builder, headers);
        if (tag != null) {
            builder.tag(tag);
        }
        Request request = builder.build();
        String content="";
        Long startTime = System.currentTimeMillis();
        Response response=null;
        try {
            response = okHttpClient.newCall(request).execute();
            if (!response.isSuccessful()) {
                throw new IOException("Unexpected code " + response);
            }
            return response;
        }catch (Throwable e){
            log.error("HTTP 调用失败 [{} {}]: {}", request.method(), request.url(), e.getMessage(), e);
            content = e.getMessage();
            throw e;
        }finally {
            long endTime = System.currentTimeMillis();
            log.info("get request cost:"+(endTime-startTime)+"ms");
            addHttpLog(request,null, response,content,startTime,endTime);
        }
    }

    /**
     * 异步GET请求
     */
    public static void asyncGet(String url, HttpCallback callback) {
        asyncGet(url, null, null, callback);
    }

    public static void asyncGet(String url, Map<String, String> headers, HttpCallback callback) {
        asyncGet(url, headers, null, callback);
    }

    public static void asyncGet(String url, Map<String, String> headers, Object tag, HttpCallback callback) {
        initClient();
        Request.Builder builder = new Request.Builder().url(url);
        addHeaders(builder, headers);
        if (tag != null) {
            builder.tag(tag);
        }
        Request request = builder.build();

        Call call = okHttpClient.newCall(request);
        if (tag != null) {
            callCache.put(tag, call);
        }

        call.enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                removeCallFromCache(tag);
                callback.onFailure(e);
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                removeCallFromCache(tag);
                try {
                    if (!response.isSuccessful()) {
                        callback.onFailure(new IOException("Unexpected code " + response));
                        return;
                    }
                    callback.onSuccess(response.body().string());
                } catch (IOException e) {
                    callback.onFailure(e);
                } finally {
                    Util.closeQuietly(response);
                }
            }
        });
    }

    /**
     * 同步POST JSON
     */
    public static Response postJson(String url, String json) throws IOException {
        return postJson(url, json, null, null);
    }

    /**
     * 构建带有Bearer Token的认证头
     * @param headers
     * @param token
     * @return
     */
    public static Map<String, String> addAuthBearerHeader(Map<String, String> headers, String token) {
        if (headers == null) {
            headers = new ConcurrentHashMap<>();
        }
        headers.put("Authorization", "Bearer " + token);
        return headers;
    }

    public static Response postJson(String url, String json, Map<String, String> headers) throws IOException {
        return postJson(url, json, headers, null);
    }

    public static Response postJson(String url, String json, Map<String, String> headers, Object tag) throws IOException {
        initClient();
        RequestBody body = RequestBody.create(json, JSON);
        Request.Builder builder = new Request.Builder().url(url).post(body);
        if(headers != null && !headers.containsKey("Content-Type"))  {
            headers.put("Content-Type", "application/json");
        }
        addHeaders(builder, headers);
        if (tag != null) {
            builder.tag(tag);
        }
        Request request = builder.build();
        String content="";
        Long startTime = System.currentTimeMillis();
        Response response=null;
        try{
            response = okHttpClient.newCall(request).execute();
            return response;
//            if (!response.isSuccessful()) {
//                log.error("HTTP 调用失败 [{} {}]: {}", request.method(), request.url(), response);
//                throw new IOException("Unexpected code " + response);
//            }
//            content = response.body().string();
//            return response.body().string();
        }catch (Throwable e){
            log.error("HTTP 调用失败 [{} {}]: {}", request.method(), request.url(), e.getMessage(), e);
            content = e.getMessage();
            throw e;
        }finally {
            long endTime = System.currentTimeMillis();
            log.info("post request cost:"+(endTime-startTime)+"ms");
            addHttpLog(request,json, response,content,startTime,endTime);
        }
    }

    /**
     * 异步POST JSON
     */
    public static void asyncPostJson(String url, String json, HttpCallback callback) {
        asyncPostJson(url, json, null, null, callback);
    }

    public static void asyncPostJson(String url, String json, Map<String, String> headers, HttpCallback callback) {
        asyncPostJson(url, json, headers, null, callback);
    }

    public static void asyncPostJson(String url, String json, Map<String, String> headers, Object tag, HttpCallback callback) {
        initClient();
        RequestBody body = RequestBody.create(json, JSON);
        Request.Builder builder = new Request.Builder().url(url).post(body);
        addHeaders(builder, headers);
        if (tag != null) {
            builder.tag(tag);
        }
        Request request = builder.build();

        Call call = okHttpClient.newCall(request);
        if (tag != null) {
            callCache.put(tag, call);
        }

        call.enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                removeCallFromCache(tag);
                callback.onFailure(e);
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                removeCallFromCache(tag);
                try {
                    if (!response.isSuccessful()) {
                        callback.onFailure(new IOException("Unexpected code " + response));
                        return;
                    }
                    callback.onSuccess(response.body().string());
                } catch (IOException e) {
                    callback.onFailure(e);
                } finally {
                    Util.closeQuietly(response);
                }
            }
        });
    }

    /**
     * 取消请求
     */
    public static void cancelRequest(Object tag) {
        if (tag != null && callCache.containsKey(tag)) {
            Call call = callCache.get(tag);
            if (call != null && !call.isCanceled()) {
                call.cancel();
            }
            callCache.remove(tag);
        }
    }

    /**
     * 添加请求头
     */
    private static void addHeaders(Request.Builder builder, Map<String, String> headers) {
        if (headers != null && !headers.isEmpty()) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                builder.addHeader(entry.getKey(), entry.getValue());
            }
        }
    }

    /**
     * 从缓存中移除Call
     */
    private static void removeCallFromCache(Object tag) {
        if (tag != null) {
            callCache.remove(tag);
        }
    }

    /**
     * HTTP回调接口
     */
    public interface HttpCallback {
        void onSuccess(String response);

        void onFailure(Exception e);
    }


    private static void addHttpLog(Request request,String requestBody, Response response, String errorMsg,Long requestTime,Long responseTime) {
        try {
            OrderApiLogProducer orderApiLog = initApiLogProducer();
            Headers headers = request.headers();
            String method = request.method();
            HttpUrl url = request.url();

            OrderApiLogMessage orderApiLogMessage = new OrderApiLogMessage();

            // 设置业务上下文信息
            if (ElmOrderThreadContext.getOrderCode() != null) {
                orderApiLogMessage.setOrderCode(ElmOrderThreadContext.getOrderCode().toString());
            } else {
                orderApiLogMessage.setOrderCode("");
            }

            if (ElmOrderThreadContext.getRefrenceNo() != null) {
                orderApiLogMessage.setReferenceNo(ElmOrderThreadContext.getRefrenceNo().toString());
            }

            // 设置请求信息
            orderApiLogMessage.setMethod(method);
            orderApiLogMessage.setUrl(url.toString());
            orderApiLogMessage.setHeaders(headers.toString());

            // 正确获取请求体内容
            orderApiLogMessage.setRequestBody(requestBody);

            // 设置响应信息
            if (response != null) {
                try {
                    String responseBody = response.peekBody(Long.MAX_VALUE).string();
                    orderApiLogMessage.setResponseBody(responseBody);
                    orderApiLogMessage.setResponseCode(String.valueOf(response.code()));
                } catch (IOException e) {
                    orderApiLogMessage.setErrorMsg("[无法读取响应体: " + e.getMessage() + "]");
                }
            } else {
                orderApiLogMessage.setErrorMsg(errorMsg != null ? errorMsg : "[无响应]");
            }
            orderApiLogMessage.setRequestTime(requestTime);
            orderApiLogMessage.setResponseTime(responseTime);
            orderApiLogMessage.setCostTime(responseTime-requestTime);
            // 发送日志
            orderApiLog.sendOrderApiLog(orderApiLogMessage);
        } catch (Exception e) {
            log.error("记录HTTP日志失败", e);
        }
    }
}
